gradle构建带三方依赖jar的普通项目

您所在的位置:网站首页 gradle 打包boot gradle构建带三方依赖jar的普通项目

gradle构建带三方依赖jar的普通项目

2024-07-12 05:34| 来源: 网络整理| 查看: 265

    gradle构建springboot项目,有默认的插件,帮助我们做了很多工作,我们只需要按照start.spring.io的步骤来构建一个项目即可。项目中的配置都自动帮助我们生成好了,无需关心最后的启动类,依赖关系。我们先看看springboot项目的构建文件build.gradle:

plugins { id 'org.springframework.boot' version '2.2.0.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' id 'java' } group = 'com.xxx' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/'} //mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } } test { useJUnitPlatform() }

    构建是要生成jar包的,但是配置文件里面没有jar的关键字,这是因为springboot的插件帮我们做好了,当我们换成了一般的项目,比如一个jetty server的项目,或者一个带三方依赖的 可执行程序,我们需要做这样的工作:

    1、编写jar任务,     2、指定manifest      3、指定依赖,也就是指定classpath。

    下面通过一个简单的示例,来感受一下gradle构建的过程:我们新建一个项目,加入依赖org.web3j:core:4.5.5,然后编写相关代码:

package com.xxx.web3j; import org.web3j.protocol.Web3j; import org.web3j.protocol.http.HttpService; public class Web3jApp { public static void main(String[] args) throws Exception { Web3j web3j = Web3j.build(new HttpService("http://localhost:8545")); String v = web3j.web3ClientVersion().send().getWeb3ClientVersion(); System.out.println(v); } }

    默认的build.gradle文件如下:

/* * This file was generated by the Gradle 'init' task. * * This generated file contains a sample Java Library project to get you started. * For more details take a look at the Java Libraries chapter in the Gradle * User Manual available at https://docs.gradle.org/5.6.3/userguide/java_library_plugin.html */ plugins { // Apply the java-library plugin to add support for Java Library id 'java-library' } repositories { // Use jcenter for resolving dependencies. // You can declare any Maven/Ivy/file repository here. jcenter() } dependencies { // This dependency is exported to consumers, that is to say found on their compile classpath. api 'org.apache.commons:commons-math3:3.6.1' // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation 'com.google.guava:guava:28.0-jre' // Use JUnit test framework testImplementation 'junit:junit:4.12' }

     为了让项目支持org.web3j,我们加入dependencies:compile 'org.web3j:core:4.5.5' ,并使用aliyun maven构建。

plugins { // Apply the java-library plugin to add support for Java Library id 'java-library' id 'java' } repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } mavenCentral() } dependencies { // This dependency is exported to consumers, that is to say found on their compile classpath. api 'org.apache.commons:commons-math3:3.6.1' compile 'org.web3j:core:4.5.5' compile 'ch.qos.logback:logback-core:1.2.3' compile 'ch.qos.logback:logback-classic:1.2.3' // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation 'com.google.guava:guava:28.0-jre' // Use JUnit test framework testImplementation 'junit:junit:4.12' }

      默认,我们不做设置,可以构建一个jar包,但是当我们运行的时候,发现提示jar包中没有指定主清单属性。

    当我们写上jar manifest Main-Class,发现会缺少依赖。我们在build.gradle文件中加入jar { manifest {attributes ()}},如下所示:

jar { manifest { attributes ( 'Manifest-Version': 1.0, 'Main-Class' : 'com.xxx.web3j.Web3jApp', 'Implementation-Title': 'Gradle' ) } }

    生成的jar包中MANIFEST.MF内容如下,相对任何都不设置的情况下,多了Main-Class:

    这种情况之下,运行还是会出现问题,会报错:ClassNotFoundException

    原因就是我们的项目依赖没有或者没有打入到jar包中。

    下面就是本文要讲述的重点了,怎么将依赖打入jar包中,是以源码的形式打,还是以lib/jar源码和依赖分开的方式,一般来说,我们是希望将三方依赖也打入jar包中,所以会选择第一种方式,但是,我们也有这样的场景,需要将我们自己的jar包和依赖分开。

     第一种方式是将三方依赖打入我们的jar包,因此运行的时候直接就能找到类,无需再指定classpath,修改jar任务的内容,如下所示:

jar { manifest { attributes ( 'Manifest-Version': 1.0, 'Main-Class' : 'com.xxx.web3j.Web3jApp', 'Implementation-Title': 'Gradle' ) } from { configurations.compile.collect { it.isDirectory()? it:zipTree(it) } } }

     运行构建,通过反编译软件查看打包的内容,我们欣喜的发现,确实将三方jar包也打入了我们自己的jar中,如下所示:

    文件中META-INF目录下,多了几个DSA,SF等后缀结尾的签名文件。 

    然后来运行,结果,还是一个莫名其妙的错误,这时候是报无效的签名文件摘要的错误:

    出错的原因就是多了DSA,SF文件,解决办法就是去掉这些文件,打包的时候排除即可,再次修改我们的jar任务:

jar { manifest { attributes ( 'Manifest-Version': 1.0, 'Main-Class' : 'com.xxx.web3j.Web3jApp', 'Implementation-Title': 'Gradle' ) } from { configurations.compile.collect { it.isDirectory()? it:zipTree(it) } } exclude 'META-INF/*.RSA','META-INF/*.SF','META-INF/*.DSA' }

     再次构建,运行,正常。

    最后介绍一下,将依赖和我们得jar包分开的打包方式,这里需要将依赖加入一个文件夹如当前文件夹lib中保存,然后再在manifest中指定Class-Path属性,需要分两步走,这里直接给出配置。   

task copyDependencies(type: Copy){ from configurations.runtime into 'build/libs/lib' } jar.dependsOn(copyDependencies) jar { manifest { attributes ( 'Manifest-Version': 1.0, 'Main-Class' : 'com.xxx.web3j.Web3jApp', 'Implementation-Title': 'Gradle' ) } if(!configurations.runtime.isEmpty()){ manifest.attributes('Class-Path': '. lib/'+ configurations.runtime.collect { it.name }.join(' lib/') ) } }

     拷贝程序运行所需要的jar到一个目录lib中,另外一定要设置 manifest的Class-Path属性。这里通过构建一个Copy类型的任务,最后再将lib/*.jar加入到Class-Path中。执行构建生成的文件结构如下所示:

    

        使用反编译工具打开jar,查看MANIFEST.MF内容:

     

     这种构建因为运行jar包和依赖jar包是分开的,使用起来也不是很方便,尤其是部署的时候。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3